<template>
  <div class="tabsX" ref="tabsDom"
       :style="{
    '--showOne': showOne.show?'inline-block':'none',
    '--iconSize':iconStyleD.fontSize,
    '--noContent': props.noContent?1:0,
  }">
    <div class="one" :class="{'all': props.closable}" v-if="props.which=='one'" :style="{width: String(widthD)+'px'}">
      <el-tabs :type="props.type" v-model="nowTab" @tab-remove="remove" :tab-position="props.position"
               @tab-change="change" @tab-click="click" :stretch="props.stretch"
               :closable="props.closable" :class="props.class">
        <el-tab-pane v-for="(tabItem,index) in tabsData" :key="index" :disabled="tabItem[paneItem.disabled]"
                     :closable="showOne.close(index)" :name="tabItem[props.name] || index">
          <template #default v-if="!props.noContent">
            <slot v-if="!tabItem.slot" name="default" :data="tabItem">
              <span class="content">{{ tabItem[props.titleField] }}</span>
            </slot>
            <slot v-else :name="tabItem.slot" :data="tabItem"></slot>
          </template>
          <template #label>
            <slot v-if="!tabItem.slotLabel" name="label" :data="tabItem">
              <span class="title">{{ tabItem[props.titleField] }}</span>
            </slot>
            <slot v-else :name="tabItem.slotLabel" :data="tabItem"></slot>
          </template>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script setup>
import {computed, onMounted, onUnmounted, ref, watch, nextTick} from 'vue'
import { ElTabs,ElTabPane } from 'element-plus'

const props = defineProps({
  which: {
    type: String,
    default: 'one'
  },
  // 当前选中的标签。注意传入时可以是下面几种类型，但发生变动更新后是Object类型
  modelValue: {
    type: [Object, String, Number, undefined],
    defautl: {}
  },
  // 标签数据
  data: {
    type: Object,
    default: [{
      id: '', // 对应props.name属性，唯一性
      title: '默认', // 必须显示字段名，需要对应titleField值
      path: '',
      fullPath: '',
      icon: '',
      params: {},
      query: {},
      show: true
    }]
  },
  // tab-pane属性，数量对应data哪个属性
  paneItem: {
    type: Object,
    default: {
      disabled: "disabled"
    }
   },
  // 标签内容字段
  titleField: {
    type: String,
    default: 'title'
  },

  // 可以关闭
  closable: {
    type: Boolean,
    default: true
  },
  // 对应Tab-pane组件的name属性。具有唯一性Objest字段
  name: {
    type: String,
    default: 'id'
  },
  type: {
    type: String,
    default: 'card'
  },

  // 宽度
  width: {
    type: [Number, String],
    default: '-1' // -1是为内容宽度
  },
  // 动态改变宽度，右边剩余宽度
  onWidth: {
    type: [Number, String],
    default: '-1'
  },

  // 第一个标签对象
  one: {
    type: Object,
    default: {
      close: undefined,  // 是否显示关闭图标。默认为closable的值
      show: true // 显示。不显示时用来v-model占位
    }
  },
  // 没有内容的父级类名搜索
  fatherClass: {
    type: String,
    default: ''
  },
  // 没有内容
  noContent: {
    type: Boolean,
    default: true
  },

  // 是否自动撑开
  stretch: {
    type: Boolean,
    default: false
  },

  // 位置
  position: {
    type: String,
    default: undefined
  },

  iconStyle: {
    type: Object,
    default: undefined // {fontSize: 16}
  },

  // 刷新tabsData数据
  refresh: {
    type: Boolean,
    default: false
  },

  // tab组件类名
  class: {
    type: String,
    default: ''
  }
})


// 标签图标样式
const iconStyleD = computed(() => {
  const result = {
    fontSize: '16px',
  }
  if (props.iconStyle?.fontSize) {
    result.fontSize = String(props.iconStyle.fontSize) + 'px'
  }
  return result
})


// 处理第一标签的显示
const showOne = computed(() => {
  let result = {
    close: (isOne) => {
      return props.closable
    },
    show: true
  }
  if (props.one.show != undefined && props.one.show == false) {
    result.show = false
  }
  if (props.one.close != undefined) {
    result.close = (isOne) => {
      // 满足上面close为false,想要修改不可关闭前，还需要判断是否为第一个
      return isOne == 0 ? props.one.close : props.closable
    }
  }
  return result
})

// 当前选中的标签页
const nowTab = ref('')

// 标签页数据
const tabsData = ref([])
// 过滤标签页
const upData = () => {
  tabsData.value = []
  // if (typeof props.data == 'object') {
  //   // 判断是否显示当前tab页
  //   props.data.forEach(item => {
  //     if (item.show != false) {
  //       tabsData.value.push(item)
  //     }
  //   })
  // }
  if (!Boolean(props.data)) {
    tabsData.value = []
  } else if (props.refresh) {
    props.data.forEach(item => {
      if (item.show != false) {
        tabsData.value.push(item)
      }
    })
  } else {
    tabsData.value = props.data
  }
}
watch(() => props.data, newV => {
  upData()
}, {immediate: true,deep: true})

watch(() => props.refresh, newV => {
  if (newV) {
    upData()
  }
})


const emit = defineEmits(['update:modelValue', 'remove', 'change', 'click'])


// 删除标签
const remove = (name) => {
  const obj = tabsData.value.find(item => item[props.name] === name)
  emit('remove', obj)
}
// 改变标签事件
const change = (name) => {
  const obj = tabsData.value.find(item => item[props.name] === name)
  // console.log(obj)
  // 判断双向绑定的类型。如果不是字符串或者数字则返回源对象，否则返回源对象的对应值
  if (typeof props.modelValue == 'string' || typeof props.modelValue == 'number') {
    emit('update:modelValue', obj[props.name])
  } else {
    emit('update:modelValue', obj)
  }

  emit('change', obj)
}
// 点击标签
const click = (pane, event) => {
  const obj = tabsData.value.find(item => item[props.name] === pane.props.name)
  emit('click', {
    pane: pane,
    event: event,
    data: obj
  })
}


// 计算标签页宽度
const tabsDom = ref('')
const widthD = ref('200px')
const caluW = () => {
  nextTick(() => {
    if (props.onWidth != '-1' && props.onWidth != -1) {
      widthD.value = window.innerWidth - tabsDom.value.offsetLeft - props.onWidth
    }
  })
}

// 数据变化也监听
watch(tabsData, () => {
  // if (props.width == '-1') {
  caluW()
  // }
})


// 同步当前标签页
const getNowTab = async () => {
  await upData()
  if (typeof props.modelValue == 'object') {
    nowTab.value = props.modelValue[props.name]
  } else {
    // 如果一开始不是对象,则根据值获取到对应对象
    const nowObj = tabsData.value.find(item => item[props.name] == props.modelValue)
    if (nowObj) {
      nowTab.value = nowObj[props.name]
    } else {
      nowTab.value = tabsData.value[0][props.name]

    }
  }
}

onMounted(() => {
  getNowTab()

  // 为自适应时才监听
  if (props.width == '-1') {
    caluW()
    window.addEventListener('resize', caluW)
  } else {
    widthD.value = props.width
  }

  // 不需要内容区
  if (props.noContent == true) {
    nextTick(() => {
      const contentDom = document.querySelector(`${props.fatherClass} .tabsX .el-tabs__content`)
      contentDom.style.display = 'none'
    })
  }
})

onUnmounted(() => {
  if (props.width == '-1') {
    window.removeEventListener('resize', caluW)
  }
})

// 设置当前选择的标签
const setTab = name => {
  nowTab.value = name
}
// 获取当前选择的标签
const getTab = () => {
  const obj = tabsData.value.find(item => item[props.name] === pane.props.name)
  return {
    name: nowTab.value,
    obj,
  }
}

defineExpose({
  setTab,
  getTab,
  nowTab
})

// 同步当前tabs页
watch(() => props.modelValue, newV => {
  getNowTab()
}, {immediate: true})
</script>

<style scoped lang='scss'>
:deep(*).all {
  .el-tabs__header {
    // 左右的移动
    @mixin allNav() {
      width: 20px;
      text-align: center;
      border-left: 1px solid #E4E7ED;
      .el-icon {
        font-size: 16px;
        color: #000;
      }
    }
    // 左
    .el-tabs__nav-prev {
      @include allNav;
    }

    // 右
    .el-tabs__nav-next {
      @include allNav;
    }

    // 是否显示第一个
    .el-tabs__item {
      &:first-child {
        display: var(--showOne);
      }

    }

    // 去边框
    .el-tabs__nav {
      border: none;
      border-top: 1px solid #E4E7ED;
    }

  }

  // tab为左边时，去外边距
  .is-left {
    margin: 0px 0px;
  }
}

// 图标样式
:deep(.el-tabs__item) {

  span {
    //height: var(--iconSize);
    i {
      //color: red;
      //font-size: var(--iconSize) !important;
    }
  }
}

.tabsX {
  //height: 100%;

  .one {
    //height: 100%;
  }

  .el-tabs {
    height: 100%;
  }
}

:deep(.el-tabs__header) {
  margin-bottom: 0px;
}

// 去掉底部下划线
.el-tabs--border-card{
  border-bottom: none;
}
</style>